#ifndef __I_NGISDATA_UDXKERNEL_H__
#define __I_NGISDATA_UDXKERNEL_H__

#include "INxUnknown.h"
#include <string>
#include <vector>

namespace NGIS
{
	namespace Data
	{
		class IUdxNode;

		enum EKernelType
		{
			EKT_NULL=0,
			EKT_INT=2,				//!<integer
			EKT_REAL=4,				//!<float with 64bit precise
			EKT_STRING=8,			//!<a string with NULL terminated
			EKT_VECTOR2=16,		//!<2 dimensions vector with x and y
			EKT_VECTOR3=32,		//!<3 dimensions vector with x, y and z
			EKT_VECTOR4=64,		//!<4 dimensions vector with x, y, z and w
			
			EKT_NODE=128,			//!<a no-constraints node container
			EKT_LIST=256,				//!<a container with same structure node
			EKT_MAP=512,				//!<a k-v map container
			EKT_TABLE=1024,			//!<a data table container

			EKT_INT_LIST=2|256,			
			EKT_REAL_LIST=4|256,			
			EKT_STRING_LIST=8|256,		
			EKT_VECTOR2_LIST=16|256,
			EKT_VECTOR3_LIST=32|256,
			EKT_VECTOR4_LIST=64|256,

			EKT_COUNT = 17
		};

		static std::string KernelType2String(EKernelType pType)
		{
			if (pType == EKernelType::EKT_NULL) return "";
			else if (pType == EKernelType::EKT_INT) return "int";
			else if (pType == EKernelType::EKT_REAL) return "real";
			else if (pType == EKernelType::EKT_STRING) return "string";
			else if (pType == EKernelType::EKT_VECTOR2) return "vector2d";
			else if (pType == EKernelType::EKT_VECTOR3) return "vector3d";
			else if (pType == EKernelType::EKT_VECTOR4) return "vector4d";
			else if (pType == (EKernelType::EKT_INT | EKernelType::EKT_LIST)) return "int_array";
			else if (pType == (EKernelType::EKT_REAL | EKernelType::EKT_LIST)) return "real_array";
			else if (pType == (EKernelType::EKT_STRING | EKernelType::EKT_LIST)) return "string_array";
			else if (pType == (EKernelType::EKT_VECTOR2 | EKernelType::EKT_LIST)) return "vector2d_array";
			else if (pType == (EKernelType::EKT_VECTOR3 | EKernelType::EKT_LIST)) return "vector3d_array";
			else if (pType == (EKernelType::EKT_VECTOR4 | EKernelType::EKT_LIST)) return "vector4d_array";
			else if (pType == EKernelType::EKT_NODE) return "any";
			else if (pType == EKernelType::EKT_LIST) return "list";
			else if (pType == EKernelType::EKT_MAP) return "map";
			else if (pType == EKernelType::EKT_TABLE) return "table";
			else if (pType == EKernelType::EKT_COUNT) return "";
			return "";
		}

		static EKernelType String2KernelType(std::string typeStr)
		{
			std::string pType = typeStr;
			if (pType == "int") return EKernelType::EKT_INT;
			else if (pType == "real") return EKernelType::EKT_REAL;
			else if (pType == "string") return EKernelType::EKT_STRING;
			else if (pType == "vector2d") return EKernelType::EKT_VECTOR2;
			else if (pType == "vector3d") return EKernelType::EKT_VECTOR3;
			else if (pType == "vector4d") return EKernelType::EKT_VECTOR4;
			else if (pType == "int_array") return (EKernelType)(EKernelType::EKT_INT | EKernelType::EKT_LIST);
			else if (pType == "real_array") return (EKernelType)(EKernelType::EKT_REAL | EKernelType::EKT_LIST);
			else if (pType == "string_array") return (EKernelType)(EKernelType::EKT_STRING | EKernelType::EKT_LIST);
			else if (pType == "vector2d_array") return (EKernelType)(EKernelType::EKT_VECTOR2 | EKernelType::EKT_LIST);
			else if (pType == "vector3d_array") return (EKernelType)(EKernelType::EKT_VECTOR3 | EKernelType::EKT_LIST);
			else if (pType == "vector4d_array") return (EKernelType)(EKernelType::EKT_VECTOR4 | EKernelType::EKT_LIST);
			else if (pType == "any") return EKernelType::EKT_NODE;
			else if (pType == "list") return EKernelType::EKT_LIST;
			else if (pType == "map") return EKernelType::EKT_MAP;
			else if (pType == "table") return EKernelType::EKT_TABLE;
			//////////////////////////////////////////////////////////////////////////
			else if (pType == "int") return EKernelType::EKT_INT;
			else if (pType == "float") return EKernelType::EKT_REAL;
			else if (pType == "string") return EKernelType::EKT_STRING;
			else if (pType == "vector2d") return EKernelType::EKT_VECTOR2;
			else if (pType == "vector3d") return EKernelType::EKT_VECTOR3;
			else if (pType == "vector4d") return EKernelType::EKT_VECTOR4;
			else if (pType == "int|array") return (EKernelType)(EKernelType::EKT_INT | EKernelType::EKT_LIST);
			else if (pType == "float|array") return (EKernelType)(EKernelType::EKT_REAL | EKernelType::EKT_LIST);
			else if (pType == "string|array") return (EKernelType)(EKernelType::EKT_STRING | EKernelType::EKT_LIST);
			else if (pType == "vector2d|array") return (EKernelType)(EKernelType::EKT_VECTOR2 | EKernelType::EKT_LIST);
			else if (pType == "vector3d|array") return (EKernelType)(EKernelType::EKT_VECTOR3 | EKernelType::EKT_LIST);
			else if (pType == "vector4d|array") return (EKernelType)(EKernelType::EKT_VECTOR4 | EKernelType::EKT_LIST);
			else if (pType == "structure") return EKernelType::EKT_NODE;
			return EKernelType::EKT_NULL;
		}

		class IUdxKernel : public INxUnknown
		{
		public:
			virtual const IUdxNode* getNode() = 0;

			virtual EKernelType getType() = 0;
		};

		//////////////////////////////////////////////////////////////////////////
		struct Vector2d
		{
			Vector2d()
			{
				x = 0; y = 0;
			}
			Vector2d(double _x, double _y)
			{
				x = _x;
				y = _y;
			}
			double x;
			double y;
		};
		struct Vector3d
		{
			Vector3d()
			{
				x = 0; y = 0; z= 0;
			}
			Vector3d(double _x, double _y, double _z)
			{
				x = _x;
				y = _y;
				z = _z;
			}
			double x;
			double y;
			double z;
		};
		struct Vector4d
		{
			Vector4d()
			{
				x = 0; y = 0; z= 0;
			}
			Vector4d(double _x, double _y, double _z, double _m)
			{
				x = _x;
				y = _y;
				z = _z;
				m = _m;
			}
			double x;
			double y;
			double z;
			double m;
		};
		//////////////////////////////////////////////////////////////////////////

		class IUdxKernelIntValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(int pValue) = 0;

			virtual int getTypedValue() = 0;
		};

		class IUdxKernelRealValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(double pValue) = 0;

			virtual double getTypedValue() = 0;
		};

		class IUdxKernelStringValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(std::string pValue) = 0;

			virtual std::string getTypedValue() = 0;
		};

		class IUdxKernelVector2dValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(double pX, double pY) = 0;

			virtual Vector2d getTypedValue() = 0;

			virtual void getTypedValue(double& pX, double& pY) = 0;
		};

		class IUdxKernelVector3dValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(double pX, double pY, double pZ) = 0;

			virtual Vector3d getTypedValue() = 0;

			virtual void getTypedValue(double& pX, double& pY, double& pZ) = 0;
		};

		class IUdxKernelVector4dValue : public IUdxKernel
		{
		public:
			virtual bool setTypedValue(double pX, double pY, double pZ, double pM) = 0;

			virtual Vector4d getTypedValue() = 0;

			virtual void getTypedValue(double& pX, double& pY, double& pZ, double& pM) = 0;
		};

		//////////////////////////////////////////////////////////////////////////

		class IUdxKernelIntArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(int pValue) = 0;

			virtual bool getTypedValueByIndex(int idx, int& val) = 0;

			virtual bool setTypedValue(int pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		class IUdxKernelRealArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(double pValue) = 0;

			virtual bool getTypedValueByIndex(int idx, double& val) = 0;

			virtual bool setTypedValue(double pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		class IUdxKernelStringArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(std::string pValue) = 0;

			virtual bool getTypedValueByIndex(int idx, std::string& val) = 0;
			
			virtual bool setTypedValue(std::string pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		class IUdxKernelVector2dArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(double pX, double pY) = 0;

			virtual bool getTypedValueByIndex(int idx, Vector2d& val) = 0;

			virtual bool getTypedValueByIndex(int idx, double& pX, double& pY) = 0;

			virtual bool setTypedValue(Vector2d pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		class IUdxKernelVector3dArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(double pX, double pY, double pZ) = 0;

			virtual bool getTypedValueByIndex(int idx, Vector3d& val) = 0;

			virtual bool getTypedValueByIndex(int idx, double& pX, double& pY, double& pZ) = 0;

			virtual bool setTypedValue(Vector3d pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		class IUdxKernelVector4dArray : public IUdxKernel
		{
		public:
			virtual bool addTypedValue(double pX, double pY, double pZ, double pM) = 0;

			virtual bool getTypedValueByIndex(int idx, Vector4d& val) = 0;

			virtual bool getTypedValueByIndex(int idx, double& pX, double& pY, double& pZ, double& pM) = 0;

			virtual bool setTypedValue(Vector4d pValue, int idx) = 0;

			virtual int getCount() = 0;

			virtual void clearValue() = 0;

			virtual bool removeValueByIndex(int idx) = 0;
		};

		//////////////////////////////////////////////////////////////////////////

		class IUdxKernelMap : public IUdxKernel
		{
		public:
			virtual int getKey() = 0;

			virtual IUdxKernel* getValueByIndex(int idx) = 0;
		};

		class IUdxKernelList : public IUdxKernel
		{
		public:
			virtual int getCount() = 0;
		};

		class IUdxKernelTable : public IUdxKernel
		{
		public:
			virtual IUdxKernel* getValueArrayByIndex(int idx) = 0;

			virtual int getCount() = 0;
		};
	}
}

#endif